package edu.vt.ece.rt.benchmark.list;

import java.util.Random;

import edu.vt.ece.rt.benchmark.bank.BankAccount;
import edu.vt.ece.rt.quorum.ClustersManager;
import edu.vt.ece.rt.quorum.Resource;
import edu.vt.ece.rt.quorum.util.Names;
import edu.vt.ece.rt.util.Logger.Logger;
import edu.vt.ece.rt.benchmark.list.List;;


public class Benchmark extends edu.vt.ece.rt.benchmark.Benchmark{

	private Random random = new Random(hashCode());
	int addition = 0;
	int delete = 0;
	
	@Override
	protected void createLocalObjects() {
		
		Integer id = ClustersManager.baseClusterId;
				
		for(int i=0; i < localObjectsCount; i++) {
				try {
					int ID = (id*localObjectsCount) + i;
					String next = (lastObject(i))? null: Integer.toString(ID + 1);
					new List(Integer.toString(ID), ID, next);
					Logger.debug(ID+ " created on "+id);
				} catch (Throwable e) {
					e.printStackTrace();
				}
		}
		
		try {
			synchronized(Resource.waitObj) {
				while (Resource.objectsRegistered !=  (localObjectsCount)*(Integer.getInteger(Names.nodes)-1)) {
					Resource.waitObj.wait();
				}
				System.out.println("Object wait over for "+id +" objects registered "+Resource.objectsRegistered);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		
	}

	boolean lastObject(int i){
		int id = ClustersManager.baseClusterId;

		boolean lastNode = (id == ((Integer.getInteger(Names.nodes) - 1)));
		boolean lastObject = (i == (localObjectsCount - 1));  

		return lastNode && lastObject;
	}
	
	@Override
	protected Object randomId() {
		return null;
	}
	
	

	@Override
	protected int getOperandsCount() {
		return 0;
	}

	@Override
	protected void readOperation(Object... ids) {
		
		int val = random.nextInt(Integer.getInteger(Names.nodes)*localObjectsCount);
//		System.out.println("Finding "+val);
		List.find(val, null);
		
	}

	@Override
	protected void writeOperation(Object... ids) {
		
		int val = random.nextInt(Integer.getInteger(Names.nodes)*localObjectsCount);
		Boolean delOp = true;
		
		if (random.nextInt(100) > 50) {
			delOp = false;
		}
		
		if (delOp) {
			Logger.debug("delete op started on "+ClustersManager.baseClusterId);
			boolean del = List.delete(val, null);
			if (del) {
//				System.out.println("Deleting "+val);
				delete= delete - val;
//				System.out.println("Deleted "+val);
			}	
		} else {
			boolean add = List.add(val, null);
			if (add) {
//				System.out.println("Adding "+val);
				addition = addition + val;
//				System.out.println("Added "+val);
			}
		}
	}

	@Override
	protected void checkSanity() {

		int n = (localObjectsCount)*Integer.getInteger(Names.nodes) - 1;
		int initialSum = (n * (n + 1))/2;
		
		System.out.println("Sum for "+ClustersManager.baseClusterId+ " is "+ List.sum(null));
		System.out.println("Initial sum is "+ initialSum);
		Logger.debug("Initial sum is "+ initialSum);
		System.out.println("Delta for "+ClustersManager.baseClusterId+ " is "+(addition + delete));
		Logger.debug("Delta for "+ClustersManager.baseClusterId+ " is "+(addition + delete));
	}


	@Override
	protected String getLabel() {
		// TODO Auto-generated method stub
		return "list-qr";
	}
}
